package com.rf.richfitwheel.admin.shiro.credentials;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.util.ByteSource;

import com.rf.richfitwheel.admin.contants.CustomToken;
import com.rf.richfitwheel.admin.sys.model.User;
import com.rf.richfitwheel.common.contants.Constant;
import com.rf.richfitwheel.common.utils.StringUtils;

import java.util.concurrent.atomic.AtomicInteger;


public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    private Cache<String, AtomicInteger> passwordRetryCache;

    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token,AuthenticationInfo info) {
//        String username = (String) token.getPrincipal();
        CustomToken upToken = (CustomToken) token;
        String cacheKey = upToken.getUsername() + (StringUtils.isNotBlank(upToken.getTenantId()) ? (":" + upToken.getTenantId()) : "");
        //获取缓存中的密码重试次数
        AtomicInteger retryCount = passwordRetryCache.get(cacheKey);
        //判断重试次数是否存在
        if (retryCount == null) {
        	//设置重试次数+1
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(cacheKey, retryCount);
        }
        //判断是否重试次数大于5
        if (retryCount.incrementAndGet() > 5) {
            //提示重试次数过多
            throw new ExcessiveAttemptsException();
        }
        
        //增加免密登录功能，使用自定义token
        //免密登录,不验证密码
        CustomToken tk = (CustomToken) token;
        if(tk.getType().equals(Constant.LoginType.NOPASSWD)){
            return true;
        }

        //匹配用户输入的token 的凭证（未加密）与系统提供的凭证（已加密）
        boolean matches = super.doCredentialsMatch(token, info);
        //判断匹配是否成功
        if (matches) {
            //清空重试缓存
            passwordRetryCache.remove(cacheKey);
        }else {
        	passwordRetryCache.put(cacheKey, retryCount);
        }
        return matches;
    }
	
	/**
	* build user password
	*/
	public String buildCredentials(User user, String password,String credentialsSalt) {
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,password,ByteSource.Util.bytes(user.getUsername() + credentialsSalt), user.getUsername());
		AuthenticationToken token = new CustomToken(user.getUsername(), password, user.getTenantId());
		return super.hashProvidedCredentials(token, authenticationInfo).toString();
    }
}
